package cn.anecansaitin.industrialization_expansion.common.item;

import cn.anecansaitin.industrialization_expansion.ModConstant;
import cn.anecansaitin.industrialization_expansion.api.common.item.IToolModule;
import cn.anecansaitin.industrialization_expansion.client.util.InputManager;
import cn.anecansaitin.industrialization_expansion.common.ToolModuleType;
import cn.anecansaitin.industrialization_expansion.common.TranslationText;
import com.ibm.icu.impl.Pair;
import net.minecraft.block.Blocks;
import net.minecraft.client.Minecraft;
import net.minecraft.client.gui.FontRenderer;
import net.minecraft.client.util.ITooltipFlag;
import net.minecraft.enchantment.Enchantment;
import net.minecraft.enchantment.EnchantmentType;
import net.minecraft.item.Item;
import net.minecraft.item.ItemStack;
import net.minecraft.item.Rarity;
import net.minecraft.item.crafting.Ingredient;
import net.minecraft.util.text.*;
import net.minecraft.world.World;
import net.minecraftforge.common.ToolType;
import org.lwjgl.glfw.GLFW;

import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;

public class CommonToolModule extends Item implements IToolModule {
    private final int energy;
    private final int durability;
    private final float destroySpeed;
    private final boolean fireResistant;
    private final float damage;
    private final float attackSpeed;
    private final float xpRepairRatio;
    private final Ingredient material;
    private final ToolModuleType moduleType;
    private final String modelName;
    private final int renderColor;
    private final String icon;
    private final List<Pair<ToolType, Integer>> toolType;
    private final boolean disabledShield;
    private final int enchantability;
    private final Set<Enchantment> enchantable;
    private final Set<EnchantmentType> enchantmentTypes;
    private List<ITextComponent> tips;
    private List<ITextComponent> tips2;

    public CommonToolModule(ModuleProperty property) {
        super(new Properties().tab(ModConstant.TABLE).rarity(Rarity.UNCOMMON));
        energy = property.energy;
        durability = property.durability;
        destroySpeed = property.destroySpeed;
        fireResistant = property.fireResistant;
        damage = property.damage;
        attackSpeed = property.attackSpeed;
        xpRepairRatio = property.xpRepairRatio;
        material = property.material;
        moduleType = property.moduleType;
        modelName = property.modelName;
        renderColor = property.renderColor;
        icon = property.icon;
        toolType = property.toolType;
        disabledShield = property.disabledShield;
        enchantability = property.enchantability;
        enchantable = property.enchantable;
        enchantmentTypes = property.enchantmentTypes;
    }

    @Override
    public void appendHoverText(@Nonnull ItemStack stack, @Nullable World world, @Nonnull List<ITextComponent> tooltip, @Nonnull ITooltipFlag flag) {
        if (world == null)
            return;

        loadTips();

        if (InputManager.isKeyDown(GLFW.GLFW_KEY_LEFT_ALT))
            tooltip.addAll(tips2);
        else
            tooltip.addAll(tips);
    }

    @Override
    public int getEnergy(ItemStack stack) {
        return energy;
    }

    @Override
    public int getDurability(ItemStack stack) {
        return durability;
    }

    @Override
    public float getDestroySpeed(ItemStack stack) {
        return destroySpeed;
    }

    @Override
    public boolean isFireImmune(ItemStack stack) {
        return fireResistant;
    }

    @Override
    public float getAttackDamage(ItemStack stack) {
        return damage;
    }

    @Override
    public float getAttackSpeed(ItemStack stack) {
        return attackSpeed;
    }

    @Override
    public float getXPRepairRatio(ItemStack stack) {
        return xpRepairRatio;
    }

    @Override
    public Ingredient getMaterial(ItemStack stack) {
        return material;
    }

    @Override
    public ToolModuleType getModuleType(ItemStack stack) {
        return moduleType;
    }

    @Override
    public List<Pair<ToolType, Integer>> getToolType(ItemStack stack) {
        return toolType;
    }

    @Override
    public boolean canDisabledShield(ItemStack stack) {
        return disabledShield;
    }

    @Override
    public int getRenderColor() {
        return renderColor;
    }

    @Override
    public String getModelName(ItemStack stack) {
        return modelName;
    }

    @Override
    public int getEnchantability(ItemStack stack) {
        return enchantability;
    }

    @Override
    public Set<Enchantment> getEnchantable(ItemStack stack) {
        return enchantable;
    }

    @Override
    public Set<EnchantmentType> getEnchantmentTypes(ItemStack stack) {
        return enchantmentTypes;
    }

    @Override
    public String getIcon() {
        return icon;
    }

    private void loadTips() {
        if (tips != null)
            return;

        FontRenderer font = Minecraft.getInstance().font;
        tips = new ArrayList<>();
        tips2 = new ArrayList<>();

        //工具类型
        tips.add(new TranslationTextComponent("text." + ModConstant.MOD_ID + ".module.tool_type").withStyle(TextFormatting.GRAY));

        if (toolType.isEmpty())
            tips.add(new StringTextComponent(" ").append(new TranslationTextComponent("text." + ModConstant.MOD_ID + ".module.null").withStyle(TextFormatting.YELLOW)));
        else {
            IFormattableTextComponent toolTypeCache = new StringTextComponent(" ");

            for (Pair<ToolType, Integer> pair : toolType) {
                if (font.width(toolTypeCache) > 120) {
                    tips.add(toolTypeCache);
                    toolTypeCache = new StringTextComponent(" ");
                }

                TranslationTextComponent level = (TranslationTextComponent) new TranslationTextComponent("text." + ModConstant.MOD_ID + ".module.tool_type.level", pair.second).withStyle(TextFormatting.YELLOW);
                IFormattableTextComponent typeAndLevel = TranslationText.getToolType(pair.first).copy().append(level);
                toolTypeCache.append(typeAndLevel).append(" ");
            }

            if (!toolTypeCache.getString().equals(" "))
                tips.add(toolTypeCache);
        }

        tips.add(new TranslationTextComponent("text." + ModConstant.MOD_ID + ".module.energy").withStyle(TextFormatting.GRAY).append(new TranslationTextComponent("text." + ModConstant.MOD_ID + ".module.energy.num", energy).withStyle(TextFormatting.DARK_AQUA)));
        tips.add(new TranslationTextComponent("text." + ModConstant.MOD_ID + ".module.durability").withStyle(TextFormatting.GRAY).append(new StringTextComponent(String.valueOf(durability)).withStyle(TextFormatting.GREEN)));
        tips.add(new TranslationTextComponent("text." + ModConstant.MOD_ID + ".module.disabled_shield").withStyle(TextFormatting.GRAY).append(new StringTextComponent(String.valueOf(disabledShield)).withStyle(TextFormatting.DARK_PURPLE)));
        tips.add(new TranslationTextComponent("text." + ModConstant.MOD_ID + ".module.destroy_speed").withStyle(TextFormatting.GRAY).append(new StringTextComponent(String.valueOf(destroySpeed)).withStyle(TextFormatting.YELLOW)));
        tips.add(new TranslationTextComponent("text." + ModConstant.MOD_ID + ".module.fire_resistant").withStyle(TextFormatting.GRAY).append(new StringTextComponent(String.valueOf(fireResistant)).withStyle(TextFormatting.RED)));
        tips.add(new TranslationTextComponent("text." + ModConstant.MOD_ID + ".module.damage").withStyle(TextFormatting.GRAY).append(new StringTextComponent(String.valueOf(damage)).withStyle(TextFormatting.BLUE)));
        //添加按键提示
        tips.add(new TranslationTextComponent("text." + ModConstant.MOD_ID + ".module.more").append(" [").withStyle(TextFormatting.GOLD).append(new TranslationTextComponent("text." + ModConstant.MOD_ID + ".key.press", "Alt").withStyle(TextFormatting.GRAY)).append("]"));
        tips.add(new StringTextComponent(""));
        tips.add(new TranslationTextComponent("text." + ModConstant.MOD_ID + ".module.tip").withStyle(TextFormatting.GOLD));

        //分页
        tips2.add(new TranslationTextComponent("text." + ModConstant.MOD_ID + ".module.attack_speed").withStyle(TextFormatting.GRAY).append(new StringTextComponent(String.valueOf(attackSpeed)).withStyle(TextFormatting.YELLOW)));
        tips2.add(new TranslationTextComponent("text." + ModConstant.MOD_ID + ".module.xp_repair_ratio").withStyle(TextFormatting.GRAY).append(new StringTextComponent(String.valueOf(xpRepairRatio)).withStyle(TextFormatting.AQUA)));
        tips2.add(new TranslationTextComponent("text." + ModConstant.MOD_ID + ".module.module_type").withStyle(TextFormatting.GRAY).append(TranslationText.getModuleType(moduleType).withStyle(TextFormatting.LIGHT_PURPLE)));
        tips2.add(new TranslationTextComponent("text." + ModConstant.MOD_ID + ".module.enchantability").withStyle(TextFormatting.GRAY).append(new StringTextComponent(String.valueOf(enchantability)).withStyle(TextFormatting.DARK_PURPLE)));
        tips2.add(new TranslationTextComponent("text." + ModConstant.MOD_ID + ".module.enchantment").withStyle(TextFormatting.GRAY));

        if (enchantable.isEmpty() && enchantmentTypes.isEmpty())
            tips2.add(new StringTextComponent(" ").append(new TranslationTextComponent("text." + ModConstant.MOD_ID + ".module.null").withStyle(TextFormatting.YELLOW)));
        else {
            //附魔类型
            IFormattableTextComponent enchantmentTypeCache = new StringTextComponent(" ");

            for (EnchantmentType type : enchantmentTypes) {
                if (font.width(enchantmentTypeCache) > 120) {
                    tips2.add(enchantmentTypeCache);
                    enchantmentTypeCache = new StringTextComponent(" ");
                }

                enchantmentTypeCache.append(TranslationText.getEnchantmentType(type).withStyle(TextFormatting.DARK_GREEN)).append(new TranslationTextComponent("text." + ModConstant.MOD_ID + ".module.enchantment.type").withStyle(TextFormatting.DARK_GREEN)).append(" ");
            }

            if (!enchantmentTypeCache.getString().equals(" "))
                tips2.add(enchantmentTypeCache);

            //具体附魔
            IFormattableTextComponent enchantmentCache = new StringTextComponent(" ");

            for (Enchantment enchantment : enchantable) {
                if (font.width(enchantmentCache) > 120) {
                    tips2.add(enchantmentCache);
                    enchantmentCache = new StringTextComponent(" ");
                }

                IFormattableTextComponent component = new TranslationTextComponent(enchantment.getDescriptionId()).withStyle(TextFormatting.GREEN).append(" ");
                enchantmentCache.append(component);
            }

            if (!enchantmentCache.getString().equals(" "))
                tips2.add(enchantmentCache);
        }

        tips2.add(new TranslationTextComponent("text." + ModConstant.MOD_ID + ".module.material").withStyle(TextFormatting.GRAY).append(material.getItems()[0].getDisplayName()));
        tips2.add(new TranslationTextComponent("text." + ModConstant.MOD_ID + ".module.more").append(" [").withStyle(TextFormatting.GOLD).append(new TranslationTextComponent("text." + ModConstant.MOD_ID + ".key.release", "Alt").withStyle(TextFormatting.WHITE)).append("]"));

        tips2.add(new StringTextComponent(""));
        tips2.add(new TranslationTextComponent("text." + ModConstant.MOD_ID + ".module.tip").withStyle(TextFormatting.GOLD));
    }

    public static class ModuleProperty {
        public int enchantability;
        public Set<Enchantment> enchantable;
        public Set<EnchantmentType> enchantmentTypes;
        private int energy = 0;
        private int durability = 0;
        private float destroySpeed = 0;
        private boolean fireResistant = false;
        private float damage = 0;
        private float attackSpeed = 0;
        private float xpRepairRatio = 0;
        private Ingredient material = Ingredient.of(Blocks.BARRIER);
        private ToolModuleType moduleType = ToolModuleType.DECORATION;
        private int renderColor = 0;
        private String modelName = "miss";
        private String icon = "miss";
        private List<Pair<ToolType, Integer>> toolType = new ArrayList<>();
        private boolean disabledShield = false;

        private ModuleProperty() {
        }

        public static ModuleProperty crate() {
            return new ModuleProperty();
        }

        public ModuleProperty energy(int capacity) {
            energy = capacity;
            return this;
        }

        public ModuleProperty durability(int durability) {
            this.durability = durability;
            return this;
        }

        public ModuleProperty destroySpeed(float speed) {
            destroySpeed = speed;
            return this;
        }

        public ModuleProperty fireResistant(boolean resistant) {
            fireResistant = resistant;
            return this;
        }

        public ModuleProperty damage(float damage) {
            this.damage = damage;
            return this;
        }

        public ModuleProperty attackSpeed(float speed) {
            attackSpeed = speed;
            return this;
        }

        public ModuleProperty xpRepairRatio(float ration) {
            xpRepairRatio = ration;
            return this;
        }

        public ModuleProperty material(Ingredient material) {
            this.material = material;
            return this;
        }

        public ModuleProperty moduleType(ToolModuleType type) {
            this.moduleType = type;
            return this;
        }

        public ModuleProperty renderColor(int color) {
            this.renderColor = color;
            return this;
        }

        public ModuleProperty modelName(String name) {
            this.modelName = name;
            return this;
        }

        public ModuleProperty icon(String name) {
            this.icon = name;
            return this;
        }

        public ModuleProperty toolType(List<Pair<ToolType, Integer>> toolType) {
            this.toolType = toolType;
            return this;
        }

        public ModuleProperty disabledShield(boolean disabledShield) {
            this.disabledShield = disabledShield;
            return this;
        }

        public ModuleProperty enchantability(int ability) {
            this.enchantability = ability;
            return this;
        }

        public ModuleProperty enchantable(Set<Enchantment> enchantments) {
            this.enchantable = enchantments;
            return this;
        }

        public ModuleProperty enchantmentTypes(Set<EnchantmentType> types) {
            this.enchantmentTypes = types;
            return this;
        }
    }
}
